package com.alibaba.citrus.ots.sales.plan.facade.service.salesplan.audit;

import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.sales.plan.model.SalesPlanReportStatusEnum;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.auditsetting.dto.Load1Request;
import com.epoch.app.bcots.auditsetting.model.AuditSetting;
import com.epoch.app.bcots.auditsetting.service.AuditSettingService;
import com.epoch.app.bcots.auditsettingdetail.dto.*;
import com.epoch.app.bcots.auditsettingdetail.model.AuditSettingDetail;
import com.epoch.app.bcots.model.dto.*;
import com.epoch.app.bcots.auditsettingdetail.service.AuditSettingDetailService;
import com.epoch.app.bcots.model.enums.AuditSettingStatusEnum;
import com.epoch.app.bcots.sales_plan.salesplanreport.model.SalesPlanReport;
import com.epoch.app.bcots.sales_plan.salesplanreport.service.SalesPlanReportService;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.bcots.service.BcOtsService;
import com.epoch.app.otsplatformenhance.enums.OrganizationTypeEnum;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class AuditSettingDetailServiceImpl implements AuditSettingDetailService {

    private final Log log = Log.getLogger(AuditSettingDetailServiceImpl.class);

    @Resource
    private BcOtsService bcOtsService;

    @Resource
    private BaseDataService baseDataService;

    @Resource(name = "auditSettingServiceImpl")
    private AuditSettingService auditSettingService;

    @Resource
    private SalesPlanReportService salesPlanReportService;

    private static final int ZERO = 0;
    private static final int ONE = 1;

    public Result<List<AuditSettingDetailResponse>> pageQueryAuditSettingDetail(PageQueryAuditSettingDetailRequest pageQueryAuditSettingDetailRequest) {
        log.info("AuditSettingDetailService.pageQueryAuditSetting.request={}", JSONObject.toJSONString(pageQueryAuditSettingDetailRequest));
        if (null == pageQueryAuditSettingDetailRequest.getAuditSettingId()) {
            return Result.fail("OTS-02-003-01-15-010", ErrorMessage.code("OTS-02-003-01-15-010", null).getDisplayErrorMessage());
        }
        AuditSettingDetailLoadListRequest request = convertRequest(pageQueryAuditSettingDetailRequest);
        Result<List<AuditSettingDetail>> result = loadList(request);
        if (!result.isSuccess()) {
            return Result.fail("OTS-02-003-01-16-028", ErrorMessage.code("OTS-02-003-01-16-028", null).getDisplayErrorMessage());
        }
        log.info("AuditSettingDetailService.loadList.result={}", JSONObject.toJSONString(result));
        return Result.listSuccess(convertResponseList(result.getResult()), result.getTotal());
    }

    public Result<String> createAuditSettingDetail(CreateAuditSettingDetailRequest createAuditSettingDetailRequest) {
        log.info("AuditSettingDetailService.createAuditSettingDetail.request={}", JSONObject.toJSONString(createAuditSettingDetailRequest));
        if (StringUtils.isEmpty(createAuditSettingDetailRequest.getOrganizationType())) {
            return Result.fail("OTS-02-003-01-15-012", ErrorMessage.code("OTS-02-003-01-15-012", null).getDisplayErrorMessage());
        }
        if (StringUtils.isEmpty(createAuditSettingDetailRequest.getRoleId())) {
            return Result.fail("OTS-02-003-01-15-013", ErrorMessage.code("OTS-02-003-01-15-013", null).getDisplayErrorMessage());
        }
        if (null == createAuditSettingDetailRequest.getAuditSettingId()) {
            return Result.fail("OTS-02-003-01-15-010", ErrorMessage.code("OTS-02-003-01-15-010", null).getDisplayErrorMessage());
        }
        //判断是否有重复审批节点
        Result<List<AuditSettingDetail>> resultList = checkRepeatDetail(createAuditSettingDetailRequest.getAuditSettingId(), 
                createAuditSettingDetailRequest.getOrganizationType(), createAuditSettingDetailRequest.getRoleId());
        if (!resultList.isSuccess()) {
            return Result.fail(resultList.getErrorCode(), resultList.getMessage());
        }
        EmployeeGetCurrentLoginResponse loginResponse = bcOtsService.employeeGetCurrentLogin();
        if (!loginResponse.getSuccess()) {
            log.info("获取登录人信息失败AuditSettingDetailService.createAuditSettingDetail.employeeGetCurrentLoginResponse={}", JSONObject.toJSONString(loginResponse));
        }
        AuditSettingDetail auditSettingDetail = new AuditSettingDetail();
        auditSettingDetail.setOrganizationType(createAuditSettingDetailRequest.getOrganizationType());
        auditSettingDetail.setRoleId(createAuditSettingDetailRequest.getRoleId());
        auditSettingDetail.setAuditSettingId(createAuditSettingDetailRequest.getAuditSettingId());
        auditSettingDetail.setAuditSequence(resultList.getResult() == null ? ONE : resultList.getResult().size() + ONE);
        auditSettingDetail.setStatus(AuditSettingStatusEnum.ENABLE.getType());
        auditSettingDetail.setGmtCreate(new Date());
        auditSettingDetail.setGmtModified(new Date());
        auditSettingDetail.setCreator(loginResponse.getEmployeeId());
        auditSettingDetail.setUpdater(loginResponse.getEmployeeId());
        auditSettingDetail.setVersion(ZERO);
        CreateResponse response = null;
        try {
            response = create(auditSettingDetail);
        } catch (Exception e) {
            log.info("审批配置详情创建失败={}", e);
            return Result.fail("OTS-02-003-01-16-029", ErrorMessage.code("OTS-02-003-01-16-029", null).getDisplayErrorMessage());
        }
        return Result.success(response.getId());
    }

    @EpochTransactional(appCode = "bc_ots", dataSourceCode = "cr_ots", dataSourceType = "app")
    public Result<Boolean> deleteAuditSettingDetail(DeleteAuditSettingDetailRequest deleteAuditSettingDetailRequest) {
        log.info("AuditSettingDetailService.deleteAuditSettingDetail.request={}", JSONObject.toJSONString(deleteAuditSettingDetailRequest));
        if (null == deleteAuditSettingDetailRequest.getId()) {
            return Result.fail("OTS-02-003-01-15-014", ErrorMessage.code("OTS-02-003-01-15-014", null).getDisplayErrorMessage());
        }
        try {
            AuditSettingDetail auditSettingDetail = load(LoadRequest.builder().id(deleteAuditSettingDetailRequest.getId()).build());
            if (null == auditSettingDetail) {
                return Result.fail("OTS-02-003-01-16-030", ErrorMessage.code("OTS-02-003-01-16-030", null).getDisplayErrorMessage());
            }
            //删除校验
            Result<Boolean> checkResult = check(auditSettingDetail);
            if (!checkResult.isSuccess()) {
                return checkResult;
            } else if (!checkResult.getResult()) {
                return Result.fail("OTS-02-003-01-16-040", ErrorMessage.code("OTS-02-003-01-16-040", null).getDisplayErrorMessage());
            }
            //删除审批节点
            DeleteResponse deleteResponse = delete(DeleteRequest.builder().id(deleteAuditSettingDetailRequest.getId()).build());
            if (deleteResponse.getCount() != ONE) {
                return Result.fail("OTS-02-003-01-16-031", ErrorMessage.code("OTS-02-003-01-16-031", null).getDisplayErrorMessage());
            }
            //判断删除的节点是不是最后一个，如果不是就重新排列审批顺序
            Result<Boolean> result = updateAuditSequence(auditSettingDetail);
            return result.isSuccess() ? Result.success(true) : Result.success(false, result.getErrorCode(), result.getMessage());
        } catch (Exception e) {
            log.info("审批配置详情删除失败={}", e);
            return Result.fail("OTS-02-003-01-16-031", ErrorMessage.code("OTS-02-003-01-16-031", null).getDisplayErrorMessage());
        }
    }

    public Result<Boolean> updateAuditSettingDetail(UpdateAuditSettingDetailRequest updateAuditSettingDetailRequest) {
        log.info("AuditSettingDetailService.updateAuditSettingDetail.request={}", JSONObject.toJSONString(updateAuditSettingDetailRequest));
        if (null == updateAuditSettingDetailRequest.getId()) {
            return Result.fail("OTS-02-003-01-15-014", ErrorMessage.code("OTS-02-003-01-15-014", null).getDisplayErrorMessage());
        }
        try {
            AuditSettingDetail auditSettingDetail = load(LoadRequest.builder().id(updateAuditSettingDetailRequest.getId()).build());
            if (null == auditSettingDetail) {
                return Result.fail("OTS-02-003-01-16-032", ErrorMessage.code("OTS-02-003-01-16-032", null).getDisplayErrorMessage());
            }
            //判断是否有重复审批节点
            Result<List<AuditSettingDetail>> resultList = checkRepeatDetail(updateAuditSettingDetailRequest.getAuditSettingId(),
                    updateAuditSettingDetailRequest.getOrganizationType(), updateAuditSettingDetailRequest.getRoleId());
            if (!resultList.isSuccess()) {
                return Result.fail(resultList.getErrorCode(), resultList.getMessage());
            }
            //更新校验
            Result<Boolean> checkResult = check(auditSettingDetail);
            if (!checkResult.isSuccess()) {
                return checkResult;
            } else if (!checkResult.getResult()) {
                return Result.fail("OTS-02-003-01-16-041", ErrorMessage.code("OTS-02-003-01-16-041", null).getDisplayErrorMessage());
            }
            //更新审批节点
            if (StringUtils.isNotEmpty(updateAuditSettingDetailRequest.getOrganizationType())) {
                auditSettingDetail.setOrganizationType(updateAuditSettingDetailRequest.getOrganizationType());
            }
            if (StringUtils.isNotEmpty(updateAuditSettingDetailRequest.getRoleId())) {
                auditSettingDetail.setRoleId(updateAuditSettingDetailRequest.getRoleId());
            }
            auditSettingDetail.setVersion(auditSettingDetail.getVersion() + ONE);
            UpdateResponse updateResponse = update(auditSettingDetail);
            if (updateResponse.getCount() != ONE) {
                return Result.fail("OTS-02-003-01-16-033", ErrorMessage.code("OTS-02-003-01-16-033", null).getDisplayErrorMessage());
            }
            return Result.success(true);
        } catch (Exception e) {
            log.info("审批配置详情修改失败={}", e);
            return Result.fail("OTS-02-003-01-16-033", ErrorMessage.code("OTS-02-003-01-16-033", null).getDisplayErrorMessage());
        }
    }

    private List<AuditSettingDetailResponse> convertResponseList(List<AuditSettingDetail> auditSettingDetailList) {
        //获取角色信息
        Map<String, String> roleSDOMap = getRoleSDOMap();
        //查询员工
        Set<String> employeeIds = auditSettingDetailList.stream().map(AuditSettingDetail::getCreator).collect(Collectors.toSet());
        employeeIds.addAll(auditSettingDetailList.stream().map(AuditSettingDetail::getUpdater).collect(Collectors.toSet()));
        Map<String, String> employeeSDOMap = getEmployeeSDOMap(employeeIds);
        Map<String, String> organizationTypeMap = Arrays.stream(OrganizationTypeEnum.values()).collect(Collectors.toMap(x -> x.getCode().toString(), OrganizationTypeEnum::getDesc));
        List<AuditSettingDetailResponse> list = new ArrayList<>();
        for (AuditSettingDetail auditSettingDetail : auditSettingDetailList) {
            list.add(convertResponse(roleSDOMap, employeeSDOMap, organizationTypeMap, auditSettingDetail));
        }
        return list;
    }

    private Map<String, String> getEmployeeSDOMap(Set<String> employeeIds) {
        Map<String, String> employeeSDOMap = new HashMap<>();
        Result<List<EmployeeSDO>> employeeResult = baseDataService.baselineGetEmployeeByIdsAll(BaselineGetEmployeeByIdsAllRequest.builder()
                .ids(new ArrayList<String>(employeeIds)).build());
        if (!employeeResult.isSuccess() || CollectionUtils.isEmpty(employeeResult.getResult())) {
            log.info("查询员工信息失败AuditSettingDetailService.convertResponseList.employeeIds={}", JSONObject.toJSONString(employeeIds));
        } else {
            employeeSDOMap = employeeResult.getResult().stream().collect(Collectors.toMap(EmployeeSDO::getId, EmployeeSDO::getName, (a, b) -> a));
        }
        return employeeSDOMap;
    }

    private Map<String, String> getRoleSDOMap() {
        Map<String, String> roleSDOMap = new HashMap<>();
        Result<List<RoleSDO>> result = bcOtsService.getAllRoles(GetAllRolesRequest.builder().belongOrganizationId("1").build());
        if (!result.isSuccess() || CollectionUtils.isEmpty(result.getResult())) {
            log.info("查询角色信息失败AuditSettingDetailService.convertResponseList");
        } else {
            roleSDOMap = result.getResult().stream().collect(Collectors.toMap(RoleSDO::getId, RoleSDO::getName, (a, b) -> a));
        }
        return roleSDOMap;
    }

    private AuditSettingDetailResponse convertResponse(Map<String, String> roleSDOMap, Map<String, String> employeeSDOMap, Map<String, String> organizationTypeMap, AuditSettingDetail auditSettingDetail) {
        AuditSettingDetailResponse response = new AuditSettingDetailResponse();
        response.setId(auditSettingDetail.getId());
        response.setAuditSettingId(auditSettingDetail.getAuditSettingId());
        response.setAuditSequence(auditSettingDetail.getAuditSequence());
        response.setOrganizationType(auditSettingDetail.getOrganizationType());
        response.setOrganizationTypeName(organizationTypeMap.get(auditSettingDetail.getOrganizationType()));
        response.setParentType(auditSettingDetail.getParentType());
        response.setParentTypeName(organizationTypeMap.get(auditSettingDetail.getParentType()));
        response.setRoleId(auditSettingDetail.getRoleId());
        response.setRoleName(roleSDOMap.get(auditSettingDetail.getRoleId()));
        response.setStatus(auditSettingDetail.getStatus());
        if (null != AuditSettingStatusEnum.of(auditSettingDetail.getStatus())) {
            response.setStatusDesc(AuditSettingStatusEnum.of(auditSettingDetail.getStatus()).getDesc());
        }
        response.setGmtCreate(auditSettingDetail.getGmtCreate());
        response.setGmtModified(auditSettingDetail.getGmtModified());
        response.setCreator(auditSettingDetail.getCreator());
        response.setCreatorName(employeeSDOMap.get(auditSettingDetail.getCreator()));
        response.setUpdater(auditSettingDetail.getUpdater());
        response.setUpdaterName(employeeSDOMap.get(auditSettingDetail.getUpdater()));
        response.setVersion(auditSettingDetail.getVersion());
        return response;
    }

    private AuditSettingDetailLoadListRequest convertRequest(PageQueryAuditSettingDetailRequest pageQueryAuditSettingDetailRequest) {
        AuditSettingDetailLoadListRequest request = AuditSettingDetailLoadListRequest.newAuditSettingDetailLoadListRequestBuilder().build();
        request.setAuditSettingId(pageQueryAuditSettingDetailRequest.getAuditSettingId());
        request.setStart(pageQueryAuditSettingDetailRequest.getStart());
        request.setLimit(pageQueryAuditSettingDetailRequest.getLimit());
        request.setPage(pageQueryAuditSettingDetailRequest.getPage());
        request.setSize(pageQueryAuditSettingDetailRequest.getSize());
        request.setAsc(true);
        return request;
    }

    private Result<List<AuditSettingDetail>> checkRepeatDetail(Long auditSettingId, String organizationType, String roleId) {
        if (null == auditSettingId) {
            return Result.fail("OTS-02-003-01-15-010", ErrorMessage.code("OTS-02-003-01-15-010", null).getDisplayErrorMessage());
        }
        Result<List<AuditSettingDetail>> resultList = loadList(AuditSettingDetailLoadListRequest.newAuditSettingDetailLoadListRequestBuilder()
                .auditSettingId(auditSettingId).build());
        if (!resultList.isSuccess()) {
            return Result.fail("OTS-02-003-01-16-028", ErrorMessage.code("OTS-02-003-01-16-028", null).getDisplayErrorMessage());
        }
        if (CollectionUtils.isNotEmpty(resultList.getResult())) {
            List<AuditSettingDetail> list = resultList.getResult().stream().filter(x ->
                    x.getOrganizationType().equals(organizationType) && x.getRoleId().equals(roleId))
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(list)) {
                return Result.fail("OTS-02-003-01-16-034", ErrorMessage.code("OTS-02-003-01-16-034", null).getDisplayErrorMessage());
            }
        }
        return resultList;
    }

    private Result<Boolean> updateAuditSequence(AuditSettingDetail auditSettingDetail) {
        log.info("AuditSettingDetailService.updateAuditSequence.request={}", JSONObject.toJSONString(auditSettingDetail));
        Result<List<AuditSettingDetail>> result = loadList(AuditSettingDetailLoadListRequest.newAuditSettingDetailLoadListRequestBuilder()
                .auditSettingId(auditSettingDetail.getAuditSettingId()).sequence(auditSettingDetail.getAuditSequence()).build());
        if (!result.isSuccess()) {
            return Result.fail("OTS-02-003-01-16-036", ErrorMessage.code("OTS-02-003-01-16-036", null).getDisplayErrorMessage());
        }
        if (CollectionUtils.isNotEmpty(result.getResult())) {
            result.getResult().forEach(x -> {
                try {
                    x.setAuditSequence(x.getAuditSequence() - ONE);
                    UpdateResponse updateResponse = update(x);
                    if (updateResponse.getCount() != ONE) {
                        log.info("AuditSettingDetailService更新审批顺序失败,审批节点id={}", x.getId());
                        throw new FacadeException(ErrorMessage.code("OTS-02-003-01-16-036"));
                    }
                } catch (Exception e) {
                    log.info("AuditSettingDetailService更新审批顺序失败={}", e);
                }
            });
        }
        return Result.success(true);
    }

    /**
     * 校验能否删除或修改
     * @param auditSettingDetail
     * @return
     */
    private Result<Boolean> check(AuditSettingDetail auditSettingDetail) {
        AuditSetting auditSetting = auditSettingService.load1(Load1Request.builder().id(auditSettingDetail.getAuditSettingId()).build());
        if (null == auditSetting) {
            return Result.fail(false, "OTS-02-003-01-16-023", ErrorMessage.code("OTS-02-003-01-16-023", null).getDisplayErrorMessage());
        }
        if (StringUtils.isEmpty(auditSetting.getOrgBusinessUnitCode())) {
            return Result.fail("OTS-02-003-01-15-008", ErrorMessage.code("OTS-02-003-01-15-008", null).getDisplayErrorMessage());
        }
        if (StringUtils.isEmpty(auditSetting.getType())) {
            return Result.fail("OTS-02-003-01-15-009", ErrorMessage.code("OTS-02-003-01-15-009", null).getDisplayErrorMessage());
        }
        if (StringUtils.isEmpty(auditSetting.getOrgChannelCode())) {
            return Result.fail("OTS-02-003-01-15-016", ErrorMessage.code("OTS-02-003-01-15-016", null).getDisplayErrorMessage());
        }
        //拉取所有组织，获取当前审批配置业务单元下的所有组织id
        Result<List<OrganizationSDO>> organizationResult = baseDataService.baselineGetAllOrganization2();
        if (!organizationResult.isSuccess() || CollectionUtils.isEmpty(organizationResult.getResult())) {
            return Result.fail(false, "OTS-02-003-01-16-038", ErrorMessage.code("OTS-02-003-01-16-038", null).getDisplayErrorMessage());
        }
        List<OrganizationSDO> organizationList = organizationResult.getResult().stream().filter(organizationSDO ->
                organizationSDO.getId().equals(auditSetting.getOrgBusinessUnitCode()) ||
                organizationSDO.getParentId().equals(auditSetting.getOrgBusinessUnitCode()) ||
                organizationSDO.getId().equals(auditSetting.getOrgChannelCode()) ||
                organizationSDO.getParentId().equals(auditSetting.getOrgChannelCode())).collect(Collectors.toList());
        //根据部门id查询员工，获取业务员员工id
        List<String> ids = organizationList.stream().filter(organizationSDO ->
                organizationSDO.getType().equals(OrganizationTypeEnum.SALES_DEPARTMENT.getCode()))
                .map(OrganizationSDO::getId).collect(Collectors.toList());
        List<EmployeeSDO> list = new ArrayList<>();
        for (String id : ids) {
            Result<List<EmployeeSDO>> employeeResult = baseDataService.baselineGetEmployeesByRelationOrgId2(BaselineGetEmployeesByRelationOrgId2Request.builder()
                    .id(id).build());
            if (!employeeResult.isSuccess() || CollectionUtils.isEmpty(employeeResult.getResult())) {
                log.info("AuditSettingDetailServiceImpl.check查询部门下业务员失败,部门id={}", id);
                continue;
            }
            list.addAll(employeeResult.getResult());
        }
        //根据bizId(组织id+业务员id)和状态查询未完成的提报单
        if (CollectionUtils.isEmpty(list)) {
            return Result.fail(false, "OTS-02-003-01-16-042", ErrorMessage.code("OTS-02-003-01-16-042", null).getDisplayErrorMessage());
        }
        List<String> bizIdList = list.stream().map(EmployeeSDO::getId).collect(Collectors.toList());
        bizIdList.addAll(organizationList.stream().map(OrganizationSDO::getId).collect(Collectors.toList()));
        List<Integer> statusList = Lists.newArrayList(SalesPlanReportStatusEnum.TO_REPORT.getCode(), SalesPlanReportStatusEnum.REPORTED.getCode());
        log.info("AuditSettingDetailServiceImpl.check.bizIdList={}",JSONObject.toJSONString(bizIdList));
        Result<List<SalesPlanReport>> reportResult = null;
        try {
            reportResult = salesPlanReportService.loadSalesPlanReportList(SalesPlanReportLoadListRequest.newSalesPlanReportLoadListRequestBuilder()
                    .bizIdList(bizIdList).statusList(statusList).model(Integer.parseInt(auditSetting.getType())).build());
            log.info("AuditSettingDetailServiceImpl.check.reportResult={}",JSONObject.toJSONString(reportResult));
        } catch (Exception e) {
            log.info("AuditSettingDetailServiceImpl.check查询提报单信息失败={}", e);
            return Result.fail(false, "OTS-02-003-01-16-039", ErrorMessage.code("OTS-02-003-01-16-039", null).getDisplayErrorMessage());
        }
        return CollectionUtils.isEmpty(reportResult.getResult()) ? Result.success(true) : Result.success(false);
    }
}
